home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / raytrace / rayshade / graphtal.lzh / Graphtal.Amiga / Sphere.C < prev    next >
C/C++ Source or Header  |  1992-11-19  |  3KB  |  148 lines

  1. /*
  2.  * Sphere.C - methods for sphere manipulations.
  3.  *
  4.  * Copyright (C) 1992, Christoph Streit (streit@iam.unibe.ch)
  5.  *                     University of Berne, Switzerland
  6.  * Copyright (C) 1989, 1991, Craig E. Kolb
  7.  * All rights reserved.
  8.  *
  9.  * This software may be freely copied, modified, and redistributed
  10.  * provided that this copyright notice is preserved on all copies.
  11.  *
  12.  * You may not distribute this software, in whole or in part, as part of
  13.  * any commercial product without the express consent of the authors.
  14.  *
  15.  * There is no warranty or other guarantee of fitness of this software
  16.  * for any purpose.  It is provided solely "as is".
  17.  *
  18.  */
  19.  
  20. #include "Sphere.h"
  21.  
  22. //___________________________________________________________ Sphere
  23.  
  24. Sphere::Sphere(real radius, const Vector& position)
  25. : r(radius), center(position)
  26. {
  27.   rsqr = r*r;
  28. }
  29.  
  30. GeoObject* Sphere::create(real radius, const Vector& position)
  31. {
  32.   if (radius < EPSILON)
  33.     return NULL;
  34.  
  35.   return new Sphere(radius, position);
  36. }
  37.  
  38. /*
  39.  * Compute the intersection between a ray and a sphere.
  40.  * This algorithm is adapted from Craig Kolbs rayshade.
  41.  */
  42.  
  43. int Sphere::intersect(const Ray& ray, real minDist, real& maxDist) 
  44. {
  45.   real xadj, yadj, zadj;
  46.   real b, t, s;
  47.  
  48.   intersectionTests++;
  49.  
  50.   /*
  51.    * Translate ray origin to object space and negate everything.
  52.    * (Thus, we translate the sphere into ray space, which saves
  53.    * us a couple of negations below.)
  54.    */
  55.   xadj = center[0] - ray.getOrig()[0];
  56.   yadj = center[1] - ray.getOrig()[1];
  57.   zadj = center[2] - ray.getOrig()[2];
  58.  
  59.   /*
  60.    * Solve quadratic equation.
  61.    */
  62.   b = xadj*ray.getDir()[0] + yadj*ray.getDir()[1] + zadj*ray.getDir()[2];
  63.   t = b*b - xadj*xadj - yadj*yadj - zadj*zadj + rsqr;
  64.   if (t < 0.) 
  65.     return FALSE;
  66.  
  67.   t = sqrt(t);
  68.  
  69.   /*
  70.    * we may hit the sphere twice, test both cases
  71.    */
  72.   s = b - t;
  73.   if (s > minDist) {
  74.     if (s < maxDist) {
  75.       maxDist = s;
  76.       return TRUE;
  77.     }
  78.     return FALSE;
  79.   }
  80.  
  81.   s = b + t;
  82.   if (s > minDist && s < maxDist) {
  83.     maxDist = s;
  84.     intersections++;
  85.     return TRUE;
  86.   }
  87.   return FALSE;
  88. }
  89.  
  90. /*
  91.  * Compute sphere normal.
  92.  */
  93.  
  94. Vector Sphere::normal(const Vector& p) const
  95. {
  96.   return (p-center)/r;
  97. }
  98.  
  99. /*
  100.  * tesselate splits the sphere into polygons.
  101.  */
  102.  
  103. PolygonList* Sphere::tesselate(const BoundingBox&)
  104. {
  105.   PolygonList* polys = tesselation(center, r, 10);
  106.  
  107.   if (trans != NULL) {
  108.     for (register long i=0; i<polys->count(); i++)
  109.       polys->item(i)->transform(*trans);
  110.   }
  111.    
  112.   return polys;
  113. }
  114.  
  115. /*
  116.  * General sphere tesselation.
  117.  */
  118.  
  119. PolygonList* Sphere::tesselation(const Vector& pos, real r, int res)
  120. {
  121.   real delta = M_PI/res;
  122.   PolygonList* polySphere = new PolygonList(3*res);
  123.   Vector A, B, C, D;
  124.  
  125.   for (real alpha=0; alpha < 2*M_PI; alpha += delta) {
  126.     A = B = Vector(0,0,-r)+pos;
  127.     for (real beta=-M_PI_2+delta; beta<=M_PI_2-delta; beta += delta) {
  128.       C = computeSurfacePoint(alpha+delta, beta)*r+pos;
  129.       D = computeSurfacePoint(alpha, beta)*r+pos;
  130.       if (A==B)
  131.     polySphere->append(new Polygon(A, C, D));
  132.       else
  133.     polySphere->append(new Polygon(A, B, C, D));
  134.       A=D; B=C;
  135.     }
  136.     polySphere->append(new Polygon(A, B, Vector(0,0,r)+pos));
  137.   }
  138.   return polySphere;
  139. }
  140.  
  141. Vector Sphere::computeSurfacePoint(real alpha, real beta)
  142. {
  143.   real sin_a, cos_a, sin_b, cos_b;
  144.   SinCos(alpha, sin_a, cos_a);
  145.   SinCos(beta, sin_b, cos_b);
  146.   return Vector(cos_a*cos_b, sin_a*cos_b, sin_b);
  147. }
  148.